<script setup lang="ts">
  import { ContextRender } from "./ContextRender";
  import RainStar from "./RainStar";
  import Star from "./Star";

  const canvas = ref<HTMLCanvasElement | null>();
  // const max = ref(100);
  const max = ref(100);
  // 定义外部使用的属性 showRainStar、max、color
  const props = defineProps({
    /** 是否显示流星 */
    showRainStar: {
      type: Boolean,
      default: false,
    },
    // /** 最大显示星星数量 */
    // max: {
    //   type: Number,
    //   default: 100,
    // },
    /** 流星及星星颜色 */
    color: {
      type: String,
      default: "rgba(237, 205, 163, 1)",
    },
  });
  // 需要绘制的元素
  let renders: ContextRender[] = [];
  let animId: number; // 动画Id
  const resizeObserver = new ResizeObserver(entries => {
    console.log("resizeObserver", entries);
    // 当尺寸发生变化时，可以先暂停动画，增加执行效率
    cancelAnimationFrame(animId);
    for (const entry of entries) {
      const { width, height } = entry.contentRect;
      canvas.value!.width = width >> 0;
      canvas.value!.height = height >> 0;
    }
    max.value = (canvas.value!.width * canvas.value!.height) / 22600; // 根据屏幕来自动计算星星的数量，平均 22600 像素一个星星
    // 清除绘制的元素
    renders.splice(0, renders.length);
    // 重新开始动画（会重新生成元素）
    startAnimation();
  });

  // const canvasInfo = computed(() => {
  //   const { width, height } = canvas.value!.getBoundingClientRect();
  //   return { width, height };
  // });
  const canvasContext = computed(() => canvas.value!.getContext("2d"));

  onMounted(() => {
    // 监听 canvas 的大小变化事件
    resizeObserver.observe(canvas.value!);
    startAnimation();
  });

  onBeforeUnmount(() => {
    renders = [];
    resizeObserver.unobserve(canvas.value!);
    cancelAnimationFrame(animId);
  });

  function resetCanvas(context: CanvasRenderingContext2D) {
    context.globalCompositeOperation = "source-over";
    context.clearRect(0, 0, context.canvas.width, context.canvas.height);
    context.globalCompositeOperation = "lighter";
  }
  // 开始动画
  function startAnimation() {
    const { color, showRainStar } = props;
    const { width, height } = canvas.value!.getBoundingClientRect();
    const cacheCanvas = document.createElement("canvas");
    cacheCanvas.width = width;
    cacheCanvas.height = height;
    const cacheContext = cacheCanvas.getContext("2d");

    // 初始化流星
    if (showRainStar) {
      const rainStar = new RainStar({ x: Math.random() * width, y: Math.random() * height }, color);
      renders.push(rainStar);
    }
    // 初始化星星
    for (let index = 0; index < max.value; index++) {
      const star = new Star({ x: Math.random() * width, y: Math.random() * height }, color);
      renders.push(star);
    }

    animId = requestAnimationFrame(animationFrame);

    // 执行动画帧
    function animationFrame() {
      resetCanvas(cacheContext); // 重置 canvas
      const removeRenderIndex: number[] = []; // 记录需要删除的元素位置
      renders.forEach((item, index) => {
        if (item.isDestory) {
          removeRenderIndex.unshift(index); // 倒序插入，删除时从后往前删除
        } else {
          item.update(cacheContext);
        }
      });

      resetCanvas(canvasContext.value); // 重置 canvas
      canvasContext.value.drawImage(cacheCanvas, 0, 0);

      removeRenderIndex.forEach(itemIndex => {
        renders.splice(itemIndex, 1);
      });

      // 生成流星的概率
      if (props.showRainStar && Math.random() < 0.01) {
        const rainStar = new RainStar({ x: Math.random() * width, y: Math.random() * height }, color);
        renders.push(rainStar);
      }
      // 生成星星的概率 及 阈值
      if (Math.random() < 0.5 && renders.length < max.value) {
        // 随机生成 1~2 个新的星星
        for (let index = 0, length = Math.random() * 2 + 1; index < length && renders.length < max.value; index++) {
          const star = new Star({ x: Math.random() * width, y: Math.random() * height }, color);
          renders.push(star);
        }
      }

      animId = requestAnimationFrame(animationFrame);
    }
  }
</script>

<template>
  <canvas ref="canvas"
          class="pe-none"></canvas>
</template>
